package com.fy.service.imbusiness.service.impl;


import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.fy.framework.common.constant.RedisKey;
import com.fy.framework.common.model.R;
import com.fy.framework.common.model.RSAKey;
import com.fy.framework.common.utils.AesEncodeUtil;
import com.fy.framework.common.utils.JwtToken;
import com.fy.framework.common.utils.RSAUtils;
import com.fy.framework.component.config.LocaleMessage;
import com.fy.framework.component.config.RedissonComponet;
import com.fy.common.entity.SkImUser;
import com.fy.common.dto.UserRegisterAndLoginDto;
import com.fy.service.imbusiness.service.RegisterAndLoginService;
import com.fy.service.service.SkImUserService;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

import static com.fy.service.component.util.RedisKeyUtil.deviceIdKey;

/**
 * @author zhshuo
 * @date 2021/11/29 17:43
 **/
@Slf4j
@Service
@Deprecated
@AllArgsConstructor
public class RegisterAndLoginServiceImpl implements RegisterAndLoginService {

    SkImUserService userService;

    LocaleMessage localeMessage;

    RedissonComponet redissonComponet;

    BCryptPasswordEncoder bCryptPasswordEncoder;

    @Override
    public R<?> doUserRegister(UserRegisterAndLoginDto registerAndLoginDto) {
        R<?> userInfoCheck = userInfoCheck(registerAndLoginDto);
        if(Objects.nonNull(userInfoCheck)) return userInfoCheck;
        if(Objects.nonNull(userService.selectOne(new EntityWrapper<SkImUser>().eq("account", registerAndLoginDto.getAccount())))){
            return R.failedAlter(localeMessage.getMessage("im.user.accountExisted"));
        }
        userService.insert(new SkImUser().setAccount(registerAndLoginDto.getAccount()).setPassword(bCryptPasswordEncoder.encode(registerAndLoginDto.getPassword())));
        redissonComponet.delete(registerAndLoginDto.getDeviceId());
        return R.success(localeMessage.getMessage("im.user.accountRegisterSuccess"));
    }

    @Override
    public R<?> token(UserRegisterAndLoginDto registerAndLoginDto) {
        R<?> userInfoCheck = userInfoCheck(registerAndLoginDto);
        if(Objects.nonNull(userInfoCheck)) return userInfoCheck;
        SkImUser skImUser = userService.selectOne(new EntityWrapper<SkImUser>().eq("account", registerAndLoginDto.getAccount()));
        if(Objects.isNull(skImUser)){
            return R.failedAlter(localeMessage.getMessage("im.user.accountNotExisted"));
        }
        if(!bCryptPasswordEncoder.matches(registerAndLoginDto.getPassword(),skImUser.getPassword())){
            return R.failedAlter(localeMessage.getMessage("im.user.passwordNotMatch"));
        }

        RSAKey generateRSAKey = RSAUtils.generateRSAKey();
        Map<String,Object> claim = new HashMap<>();
        claim.put("userInfo",skImUser);
        claim.put("public_key",generateRSAKey.getPublicKeyStr());

        final String token = JwtToken.generateToken(claim,
                registerAndLoginDto.getAccount());
        Boolean set = redissonComponet.setMap(RedisKey.USER_TOKEN_PRE, registerAndLoginDto.getAccount(), token, 31, TimeUnit.DAYS);
        Map<String, Object> tokenInfo = new HashMap<>();
        tokenInfo.put("access_token", AesEncodeUtil.encrypt(token));
        tokenInfo.put("userId", String.valueOf(skImUser.getId()));
        tokenInfo.put("public_key", generateRSAKey.getPublicKeyStr());
        tokenInfo.put("username", skImUser.getAccount());
        return R.success(tokenInfo);
    }

    private R<?> userInfoCheck(UserRegisterAndLoginDto registerAndLoginDto){
        String account = registerAndLoginDto.getAccount();
        String password = registerAndLoginDto.getPassword();
        String deviceId = registerAndLoginDto.getDeviceId();
        String validateCode = registerAndLoginDto.getValidateCode();

        if(StringUtils.isBlank(account) || StringUtils.isBlank(password)){
            return R.failedAlter(localeMessage.getMessage("im.user.accountOrPasswordIsNull"));
        }
        if(StringUtils.isNotBlank(deviceId) && StringUtils.isNotBlank(validateCode)){
            String deviceIdKey = deviceIdKey(deviceId);
            Object value = redissonComponet.getValue(deviceIdKey);
            if(Objects.isNull(value)){
                return R.failedAlter(localeMessage.getMessage("im.user.verificationCodeExpired"));
            }
            if(!value.toString().equalsIgnoreCase(validateCode)){
                return R.failedAlter(localeMessage.getMessage("im.user.verificationCodeError"));
            }
        }
        return null;
    }

}
